package com.motong.gongdan.controller.system;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.motong.gongdan.config.ResponseData;
import com.motong.gongdan.config.auth.JwtConfig;
import com.motong.gongdan.config.auth.PassToken;
import com.motong.gongdan.config.auth.UserLoginToken;
import com.motong.gongdan.entity.Factory;
import com.motong.gongdan.entity.User;
import com.motong.gongdan.entity.UserMenu;
import com.motong.gongdan.service.*;
import com.motong.gongdan.util.*;
import com.motong.gongdan.vo.system.otherVo.CustomFieldVo;
import com.motong.gongdan.vo.system.otherVo.LoginVo;
import com.motong.gongdan.vo.system.otherVo.MenuJsonVo;
import com.motong.gongdan.vo.resp.LoginResp;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Api(value = "后台登陆", tags = {"后台登陆"})
@RestController
@RequestMapping(value = "/sys/login")
public class LoginController {
    @Resource
    UserService userService;
    @Resource
    SysMenuService sysMenuService;
    @Resource
    UserMenuService userMenuService;
    @Resource
    FactoryService factoryService;
    @Resource
    CustomFieldService customFieldService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;


    @PassToken
    @ApiOperation("登陆")
    @RequestMapping(value = "do_login", method = RequestMethod.POST)
    public ResponseData doLogin(@RequestBody LoginVo vo) {
        User user = new User();
        LoginUtil.removeAll();
        if ("mobile".equals(vo.getType()) && StringUtil.isNotBlank(vo.getAccount()) && StringUtil.isNotBlank(vo.getPassword())) {
            user = userService.getOne(new QueryWrapper<User>().eq("mobile", vo.getAccount()));
            if (Objects.isNull(user)){
                return ResponseData.fail(500, "用户不存在");
            }
            Factory factory = factoryService.getById(user.getFactoryId());
            if (!StringUtils.hasLength(factory.getCode())){
                return ResponseData.fail(500, "工厂code不存在");
            }
            user = userService.getOne(new QueryWrapper<User>().eq("mobile", vo.getAccount()));
        } else if ("factory".equals(vo.getType()) && StringUtil.isNotBlank(vo.getAccount()) && StringUtil.isNotBlank(vo.getPassword())
                && StringUtil.isNotBlank(vo.getFactoryCode())) {
//            dataSourceConfig.switchDataSource(vo.getFactoryCode());
            Factory factory = factoryService.getOne(new QueryWrapper<Factory>().eq("code", vo.getFactoryCode()));
            if (factory == null) {
                return ResponseData.fail(500, "工厂code不存在");
            }
            user = userService.getOne(new QueryWrapper<User>().eq("account", vo.getAccount()).eq("factory_id", factory.getId()));
        }
        if (user == null) {
            return ResponseData.fail(500, "用户不存在");
        }

        //失败次数
        Integer errNum = Convert.toInt(Optional.ofNullable(redisTemplate.opsForValue().get("motong:gongdan:login:ErrNum:" + user.getId())).orElse(0));
        //是否5min冷却
        if (Objects.nonNull(redisTemplate.opsForValue().get("motong:gongdan:login:cd:" + user.getId()))) {
            Long cdTime = Optional.ofNullable(redisTemplate.getExpire("motong:gongdan:login:cd:" + user.getId(), TimeUnit.MINUTES)).orElse(0L);
            return ResponseData.fail(500, "登录失败" + errNum + "次，请" + (cdTime + 1) + "分钟后重试");
        }

        if (user.getState() == 1) {
            return ResponseData.fail(500, "账号已被停用,请联系管理员解锁!");
        }


        Factory factory = factoryService.getById(user.getFactoryId());
        if (!TimeUtil.afterNow(factory.getEndTime())) {
            return ResponseData.fail(500, "使用权限已过期");
        }

        if (!MD5Util.verify(vo.getPassword(), user.getPassword())) {
            //错误次数判断
            String errMsg = "用户或密码错误";
            if (errNum >= 4 && errNum < 9) {
                redisTemplate.opsForValue().set("motong:gongdan:login:cd:" + user.getId(), 1, (errNum - 3) * 5, TimeUnit.MINUTES);
                errMsg = "登录失败" + (errNum + 1) + "次，请" + ((errNum - 3) * 5) + "分钟后重试";
            }
            if (errNum == 9) {
                user.setState(1);
                userService.updateById(new User().setId(user.getId()).setState(1));
                errMsg = "登录密码当前已错误10次,账号已被停用,请联系管理员解锁!";
            }
            redisTemplate.opsForValue().set("motong:gongdan:login:ErrNum:" + user.getId(), ++errNum);
            return ResponseData.fail(500, errMsg);
        }
        redisTemplate.delete("motong:gongdan:login:ErrNum:" + user.getId());
        redisTemplate.delete("motong:gongdan:login:cd:" + user.getId());
        if (StringUtil.isNotBlank(user.getRole())) {
            List<String> list = Arrays.asList(user.getRole().split(","));
            boolean admin = list.contains("1");
            boolean produce = list.contains("2");
            boolean userAdmin = list.contains("0");
            if (!admin && produce && !userAdmin) {
                return ResponseData.fail(500, "生产人员无权登录");
            }
        }
        if (user.getState() != 0) {
            return ResponseData.fail(500, "登陆失败");
        }
        if (user.getVirtualType() != 0) {
            return ResponseData.fail(500, "登陆失败");
        }
        user.setFactoryCode(factory.getCode());
        String token = JwtConfig.getToken(user, "admin");
        UserMenu um = userMenuService.getOne(new QueryWrapper<UserMenu>().eq("user_id", user.getId()).eq("type", 0));
        LoginResp loginResp = new LoginResp();
        loginResp.setToken(token);
        if (um != null) {
            loginResp.setPermissions(um.getMenu());
            JSONArray jsonArray = JSON.parseArray(um.getMenu());
            List<MenuJsonVo> list = jsonArray.toJavaList(MenuJsonVo.class);
            List<MenuJsonVo> productList = list.stream().filter(l -> l.getPermCode().equals("production.management")).collect(Collectors.toList());
            List<MenuJsonVo> workOrderList = productList.get(0).getSubmenu().stream().filter(w -> w.getPermCode().equals("project")).collect(Collectors.toList());
            List<MenuJsonVo> lastList = workOrderList.get(0).getFiltrateConfig();
            JSONArray ja = JSONArray.parseArray(JSON.toJSONString(lastList));
            RedisUtil.set("permissions:workOrder:" + user.getId(), ja);
        }
        loginResp.setAccount(LoginUtil.getLoginAccount());
        return ResponseData.success(loginResp);
    }

    @UserLoginToken
    @ApiOperation(value = "当前登录用户信息")
    @RequestMapping(value = "login_user_mess", method = RequestMethod.POST)
    public ResponseData loginUserMess() {
        User user = userService.getById(LoginUtil.getLoginUserId());
        if (StringUtil.isNotBlank(user.getOther())) {
            List<CustomFieldVo> customFieldVos = customFieldService.handleCustomFieldForList(user.getOther());
            user.setCustomFieldVos(customFieldVos);
        }
        user.setLogoUrl("https://gongdan.motone.top/file/2022-11-29/1926d62f88b244f2bf6b291d84c55d96.jpg");
        Factory factory = factoryService.getById(user.getFactoryId());
        if (Objects.nonNull(factory) && StringUtils.hasLength(factory.getLogoUrl())) {
            user.setLogoUrl(factory.getLogoUrl());
        }
        user.setPassword(null);
        user.setFactoryId(null);
        return ResponseData.success(user);
    }


    @UserLoginToken
    @RequestMapping(value = "logout", method = RequestMethod.POST)
    public ResponseData logout() {
        Integer userId = LoginUtil.getLoginUserId();
        User user = userService.getById(userId);
        if (userId != null) {
            RedisUtil.del("JWT-TOKEN-U" + user.getAccount());
            return ResponseData.success("success");
        }
        return ResponseData.fail(500, "失败");
    }
}
